package com.it.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.entity.SysUser;
import com.it.utils.UtilJWT;
import com.it.vo.HttpResult;
import com.it.vo.SecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @author: Coke
 * @DateTime: 2023/11/12/14:07
 **/
@Component
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter {
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private UtilJWT utilJWT;
    
    @Override
    protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        log.info("请求路径为：{}",requestURI);
        
        // 判断请求的是否为登录页面
        if (!"/login/doLogin".equals(requestURI)){ // 不是登录请求，直接放行
            doFilter(request,response,filterChain); //直接下一个
            return;
        }
        //校验验证码
        validateCode(request,response,filterChain);
    }
    
    private void validateCode (HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
       // 获取用户输入的验证码
        String code = request.getParameter("code");
        // 获取session中存储的验证码
        HttpSession session = request.getSession();
        String login_captcha_code = (String) session.getAttribute("CAPTCHA_CODE");
        log.info("用户输入的验证码: {}, session中存储的验证码: {}", code, login_captcha_code);
        
        // 移除错误信息
        session.removeAttribute("captchaCodeErrorMsg");
        
        if (!StringUtils.hasText(code)){
            request.getSession().setAttribute("captchaCodeErrorMsg", "请输入验证码！");
            // 重定向到登录页面
            response.sendRedirect("/login/toLogin");
            return;
        }
        
        if (!StringUtils.hasText(login_captcha_code)){
            request.getSession().setAttribute("captchaCodeErrorMsg", "验证码错误！");
            // 重定向到登录页面
            response.sendRedirect("/login/toLogin");
        }
        
        if (!code.equalsIgnoreCase(login_captcha_code)){
            request.getSession().setAttribute("captchaCodeErrorMsg", "验证码输入错误！");
            // 重定向到登录页面
            response.sendRedirect("/login/toLogin");
        }
    
        //获取请求头中的Authorization
        String authorization = request.getHeader("Authorization");
        //如果Authorization为空，那么不允许用户访问，直接返回
        if (!StringUtils.hasText(authorization)) {
            printFront(response, "没有登录！");
            return;
        }
        //Authorization 去掉头部的Bearer 信息，获取token值
        String jwtToken = authorization.replace("Bearer ", "");
        //验签
        boolean verifyTokenResult = utilJWT.verifyToken(jwtToken);
        //验签不成功
        if (!verifyTokenResult) {
            printFront(response, "jwtToken 已过期");
            return;
        }
    
        //从payload中获取userInfo
        String userInfo = utilJWT.getUserInfo(jwtToken);
        //从payload中获取授权列表
        List<String> userAuth = utilJWT.getUserAuth(jwtToken);
        //创建登录用户
        SysUser sysUser = objectMapper.readValue(userInfo, SysUser.class);
        SecurityUser securityUser = new SecurityUser(sysUser);
        //设置权限
        List<SimpleGrantedAuthority> authList = userAuth.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
        securityUser.setSimpleGrantedAuthorities(authList);
    
    
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToke = new UsernamePasswordAuthenticationToken(securityUser
              , null, authList);
        //通过安全上下文设置认证信息
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToke);
        //继续访问相应的rul等
        filterChain.doFilter(request, response);
        // 删除session中的验证码
        session.removeAttribute("code");
        this.doFilter(request,response,filterChain);
        
    
    }
    private void printFront(HttpServletResponse response, String message) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(-1);
        httpResult.setMsg(message);
        
        writer.print(objectMapper.writeValueAsString(httpResult));
        writer.flush();
    }
}
